﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Windows.Forms;

namespace UDPModel
{
    public class UDPThread
    {
        /// <summary>
        /// 接收到的数据，最大为65507 字节。
        /// </summary>
        public Action<byte[], IPEndPoint> OnReviceMsg_Byte  = null;
        public Action<string, IPEndPoint> OnReviceMsg_String = null;
        public Action<string, string ,int > OnReviceMsg_String_IP_Port = null;

        public const int MaxDataLen = 65000;

        public UDPThread()
        {            
        }

        /// <summary>
        /// 需要向不同的终端发送数据
        /// </summary>
        /// <param name="strLocalIP"></param>
        /// <param name="iLocalSedPort"></param>
        public string Init(string strLocalIP, int iLocalSedPort)
        {
            m_local_IEP = new IPEndPoint(IPAddress.Parse(strLocalIP), iLocalSedPort);
            m_socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);

            try
            {
                m_socket.Bind(m_local_IEP);

            }
            catch (Exception ex)
            {
                return ex.ToString();
            }

            m_bStop = false;

            m_receiveThread = new Thread(Receive);
            m_receiveThread.Start();

            return "";
        }

        /// <summary>
        /// 只向同一个终端发送数据
        /// </summary>
        /// <param name="strLocalIP"></param>
        /// <param name="iLocalSedPort"></param>
        /// <param name="strRemoteIP"></param>
        /// <param name="iRemotePort"></param>
        public void Init(string strLocalIP, int iLocalSedPort, string strRemoteIP, int iRemotePort)
        {
            m_remote_IEP = new IPEndPoint(IPAddress.Parse(strRemoteIP), iRemotePort);

            Init(strLocalIP, iLocalSedPort);
        }

        /// <summary>
        /// 发送数据，最大发送65000 个字节。
        /// </summary>
        /// <param name="data"></param>
        /// <param name="strRemoteIP"></param>
        /// <param name="iRemotePort"></param>
        public bool SendData(byte[] data,string strRemoteIP,int iRemotePort)
        {
            if (data.Length <= MaxDataLen && data.Length > 0)
            {
                IPEndPoint remote_IEP = new IPEndPoint(IPAddress.Parse(strRemoteIP), iRemotePort);

                m_socket.SendTo(data, remote_IEP);

                return true;
            }

            return false;
        }
        public bool SendData(string strData, string strRemoteIP, int iRemotePort)
        {
            return SendData(System.Text.Encoding.Default.GetBytes(strData),strRemoteIP,iRemotePort);
        }

        /// <summary>
        /// 发送数据,最大发送65000 个字节。
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>使用 Init(string strLocalIP, int iLocalSedPort, string strRemoteIP, int iRemotePort)，则返回true
        public bool SendData(byte[] data)
        {
            if (m_remote_IEP != null && data.Length <= MaxDataLen)
            {
                m_socket.SendTo(data, m_remote_IEP);

                return true;
            }

            return false;
        }
        public bool SendData(string strData)
        {
            return SendData(System.Text.Encoding.Default.GetBytes(strData));
        }

        public void Finit()
        {
            m_bStop = true;
            Thread.Sleep(10);
            if (m_socket != null)
            {
                m_socket.Close();
                m_socket = null;
            }

            if (m_receiveThread != null)
            {
                bool bRet = m_DeadEvent.WaitOne(1000);
                if (bRet != true)
                {
                    m_receiveThread.Abort();
                }
                m_receiveThread = null;
            }
        }

        private void Receive()
        {
            byte[] recvBuffer = new byte[MaxDataLen];

            //远端IP
            IPEndPoint remotePoint = new IPEndPoint(IPAddress.Any, 0);

            while (m_bStop != true)
            {
                int len = 0;
                EndPoint ep = (EndPoint)remotePoint;
                try
                {
                    len = m_socket.ReceiveFrom(recvBuffer, ref ep);
                }
                catch (Exception ex)
                {
                    if (ex.HResult != -2147467259)      //0x80004005
                    {
                        MessageBox.Show("接收数据失败：" + ex.ToString());
                    }
                }
                if (len > 0 )
                {
                    byte[] tmp = recvBuffer.Take(len).ToArray();
                    if (OnReviceMsg_Byte != null)
                    {
                        OnReviceMsg_Byte(tmp, (IPEndPoint)ep);
                    }

                    if (OnReviceMsg_String != null)
                    {
                        string str = System.Text.Encoding.Default.GetString(tmp);
                        OnReviceMsg_String(str, (IPEndPoint)ep);
                    }
                    if (OnReviceMsg_String_IP_Port != null)
                    {
                        string str = System.Text.Encoding.Default.GetString(tmp);
                        IPEndPoint iPEnd = (IPEndPoint)ep;
                        string strRemoteIP = iPEnd.Address.ToString();
                        int iRemotePort = iPEnd.Port;

                        OnReviceMsg_String_IP_Port(str, strRemoteIP,iRemotePort);
                    }
                }
            }

            m_DeadEvent.Set();
        }

        /// <summary>本地(CCIEFB从站)IP终端节点
        /// 
        /// </summary>
        private IPEndPoint m_local_IEP;
        private Socket m_socket;
        private Thread m_receiveThread = null;

        /// <summary>远程(CCIEFB主站)IP终端节点
        /// 
        /// </summary>
        private IPEndPoint m_remote_IEP = null;

        //
        private bool m_bStop = false;   
        //线程结束后，设置此事件
        private AutoResetEvent m_DeadEvent = new AutoResetEvent(false);
    }
}
